import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'
import { ElMessageBox } from 'element-plus'
import { refreshToken } from '@/api/user'
import { useUserStore } from '@/store/modules/user'
import { usePermissionStore } from '@/store/modules/permission'
import router from '../router/index'
import _ from 'lodash'
import { closeWebSocket } from '@/utils/socket'
import { HMessageBox } from '@/components/common/message'
import { ref } from 'vue'
import { useGetIsUserStaySystem } from '@/services/common/useUserState'
import useCurrentRoleStore from '@/store/modules/current-role'
import useRequestHeaderFromQueryParamStore from '@/store/modules/request-header-from-query-param'

let isRefreshing = false
let refreshSubscribers = []
// 过期提醒
const returnTip = _.debounce(
  (tip) => {
    closeWebSocket()
    window.localStorage.removeItem('saasState')

    if (!useGetIsUserStaySystem()) {
      router.push({ path: '/login/index' })
    }

    const UserStore = useUserStore()
    UserStore.token = null
    UserStore.roles = []
    UserStore.row = {
      tokenValue: null, //登录token
      expireIn: null, //过期时间
      tokenStartTime: null, //登录当前时间
      refreshToken: null, //刷新token
      tokenName: null,
    }
    ElMessageBox.confirm(tip, '提示', {
      confirmButtonText: '确定',
      type: 'error',
      showCancelButton: false,
      showClose: false,
      closeOnClickModal: false,
      closeOnPressEscape: false,
      autofocus: false,
    }).then(() => {
      isRequestFail.value = false
      usePermissionStore().clearRoutes()
      useCurrentRoleStore().clearCurrentRole()

      if (useGetIsUserStaySystem()) {
        router.push({ path: '/login/index' })
      }
    })
  },
  800,
  { leading: false },
)

const service = axios.create({
  // baseURL: import.meta.env.VUE_APP_BASE_API,
  baseURL: import.meta.env.VITE_APP_BASE_API,
  timeout: 300000,
  // 跨域时候允许携带凭证
  withCredentials: true,
})

// 用来取消后续的请求，比如：当有一个api接口返回登录过期或其他错误信息，那么就通过该变量取消后续的请求
const isRequestFail = ref(false)

// 不需要刷新token的接口
const refreshTokenWhiteUrlList = [
  '/system/login/',
  '/system/login/logout',
  '/sms/loginCode',
  '/sms/registerCode',
  '/sms/updateCode',
  '/system/account/notLoginUpdatePassword',
  '/system/account/register',
  '/system/login/getCustomer',
  '/system/login/getCustomerCode',
  '/system/customer/register',
  '/system/account/getInfo',
]

service.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    if (isRequestFail.value) {
      return Promise.reject({})
    }

    if (config.headers['access-token']) {
      delete config.headers['access-token']
    }
    const UserStore = useUserStore()
    const { requestHeaderFromQueryParam } = useRequestHeaderFromQueryParamStore()
    /**
     * 用户登录之后获取服务端返回的token,后面每次请求都在请求头中带上token进行JWT校验
     * token 存储在本地储存中（storage）、vuex、pinia
     */
    // let token = UserStore.token
    const token = UserStore.row.tokenValue
    if (UserStore.row.tokenName && token) {
      config.headers[UserStore.row.tokenName] = token
    }
    if (
      requestHeaderFromQueryParam &&
      Object.keys(requestHeaderFromQueryParam).includes('RSA-TOKEN')
    ) {
      config.headers['RSA-TOKEN'] = requestHeaderFromQueryParam['RSA-TOKEN']
    }

    // 请求白名单里面的请求跳过刷新
    if (refreshTokenWhiteUrlList.includes(config.url)) {
      return config
    }

    /**
     * 判断是否刷新token，如果为正在刷新token，且请求为刷新token的路径，则直接放行
     */
    if (config.url == '/system/login/refreshToken') {
      return config
    }

    // 获取存储token的开始时间
    const tokenStartTime = UserStore.row.tokenStartTime

    // 后台给出的token有效时间，一个星期 单位 是秒
    const timeOver = UserStore.row.expireIn * 1000

    // 当前时间
    const date = new Date().getTime()

    if (token) {
      // 10分钟内刷新token
      if (timeOver - 10 * 60 * 1000 < date - tokenStartTime && date - tokenStartTime < timeOver) {
        if (!isRefreshing) {
          isRefreshing = true
          refreshToken({ refreshToken: UserStore.row.refreshToken }).then((res) => {
            UserStore.token = res.data.data.row.tokenValue
            UserStore.row = { ...res.data.data.row, tokenStartTime: new Date().getTime() }
            refreshSubscribers.forEach((cb) => cb(res.data.data.row.tokenValue))
            refreshSubscribers = []
            isRefreshing = false
          })
        }

        // 返回未执行 resolve 的Promise
        const retryOriginalRequest = new Promise((resolve) => {
          // 用函数形式 将resolve 存入，等待刷新后再执行
          refreshSubscribers.push((token) => {
            config.headers[UserStore.row.tokenName] = token
            resolve(config)
          })
        })

        // 返回config，继续原始请求
        return retryOriginalRequest
      }
      if (date - tokenStartTime > timeOver) {
        isRequestFail.value = true
        returnTip('登录过期，请重新登录')
        return Promise.reject()
      }
      return config
    }
    return config
  },
  (error: AxiosError) => {
    HMessageBox.error('操作异常，请稍后重试！')
    return Promise.reject(error)
  },
)

service.interceptors.response.use(
  (response: AxiosResponse) => {
    // if (response.data.code == 50000) {
    //   HMessageBox.error('操作异常，请稍后重试！')
    //   return false
    // } else
    if (
      response.data.code == 40100 ||
      response.data.code == 41000 ||
      response.data.code == 40101 ||
      response.data.code == 40102
    ) {
      isRequestFail.value = true
      returnTip(response.data.message)
    } else {
      return response
    }
  },
  (error: AxiosError) => {
    if (error) {
      return Promise.reject(Object.assign(error, { message: '操作异常，请稍后重试！', name: '' }))
    }

    return Promise.reject({ message: '操作异常，请稍后重试！', name: '' })
  },
)

export default service
